home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / ulib / listdir.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  7KB  |  279 lines

  1. /***********************************************************************
  2.  * $Id: listdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $
  3.  *
  4.  *.  Copyright(c) 1993,1994 by T.C. Zhao
  5.  *   All rights reserved.
  6.  *.
  7.  *
  8.  *  Semi-portable directory reader with cache. All entries will be put
  9.  *  into a structure list whose members are name and type.
  10.  ***********************************************************************/
  11. #if !defined(lint) && defined(F_ID)
  12. char *id_dlist = "$Id: listdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $";
  13. #endif
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <malloc.h>
  18. #include <limits.h>
  19. #include "ulib.h"
  20.  
  21. #ifndef PATH_MAX
  22. #define PATH_MAX 1024
  23. #endif
  24.  
  25. #define FLEN_MAX 256        /* maximum filename length w/o directory */
  26.  
  27.  
  28. /******************************************************************
  29.  * Read a directory on UNIX SysV like systems
  30.  *
  31.  *******************************************************************/
  32.  
  33. #include "unistd.h"
  34. #include <sys/types.h>
  35. #include <dirent.h>
  36. #include <sys/stat.h>
  37.  
  38. /** On Ultrix, scandir and alphasort are never decleard */
  39. #if defined(__STRICT_ANSI__)
  40.  
  41. extern int scandir(const char *dir, struct dirent **[],
  42.            int (*select) (struct dirent *),
  43.            int (*howsort) (struct dirent **, struct dirent **));
  44. extern int alphasort(struct dirent **, struct dirent **);
  45. #endif /** GCC on Ultrix */
  46.  
  47. #define MAXFL     (PATH_MAX + FLEN_MAX)
  48.  
  49. static const char *cpat;    /* current pattern          */
  50. static const char *cdir;    /* current working directory */
  51. static char fname[MAXFL + 2];
  52. static struct stat ffstat;
  53.  
  54. /******************************************************************
  55.  * Filter the filename before handing over to the "file is here" list
  56.  ******************************************************************/
  57. static int
  58. SysV_fselect(struct dirent *f)
  59.   {
  60.       strcat(strcpy(fname, cdir), f->d_name);
  61.       stat(fname, &ffstat);
  62.       /* always keep directory */
  63.       return (ffstat.st_mode & S_IFDIR) || wildmat(f->d_name, cpat);
  64.   }
  65.  
  66.  
  67. /*******************************************************************
  68.  * On entry, dir must be no zero and be terminated properly, i.e.,
  69.  * ends with /
  70.  *******************************************************************/
  71.  
  72. #ifndef M_DBG
  73. #define Tfree free
  74. #endif
  75.  
  76. static int
  77. SysV_get_entries(const char *dir, const char *pat, Dirlist ** dirlist)
  78. {
  79.     static struct dirent **dlist;
  80.     Dirlist *dl;
  81.     static int lastn;
  82.  
  83.     cpat = pat;
  84.     cdir = dir;
  85.  
  86.     /* free all memory used. If malloc wrapper is used, need to change Tfree */
  87.     if (dlist)
  88.       {
  89.       while (--lastn >= 0)
  90.           if (dlist[lastn])
  91.           Tfree(dlist[lastn]);
  92.       Tfree(dlist);
  93.       dlist = 0;
  94.       }
  95.  
  96.     /** read dir */
  97.     if ((lastn = scandir(dir, &dlist, SysV_fselect, alphasort)) > 0)
  98.       {
  99.       int i;
  100.       unsigned long mode;
  101.  
  102.       dl = *dirlist = (Dirlist *) malloc((lastn + 1) * sizeof(Dirlist));
  103.  
  104.       for (i = 0; i < lastn; i++, dl++)
  105.         {
  106.         strcat(strcpy(fname, dir), dlist[i]->d_name);
  107.         stat(fname, &ffstat);
  108.         mode = ffstat.st_mode;
  109.         dl->name = strdup(dlist[i]->d_name);
  110.         dl->type = ((mode & S_IFDIR) == S_IFDIR) ? FT_DIR :
  111.             (((mode & S_IFREG) == S_IFREG) ? FT_FILE : FT_OTHER);
  112.         }
  113.       dl->name = 0;        /* sentinel */
  114.       }
  115.     return lastn;
  116. }
  117.  
  118.  
  119. /********************************************************************
  120.  * The user routine.
  121.  *
  122.  * Get a list of files in directory, subject to pattern matching,
  123.  * and return the file list. Rescan will force a read even the requested
  124.  * directory is cached.
  125.  *
  126.  ********************************************************************/
  127.  
  128. #define MAXCACHE 10
  129.  
  130. static char *lastdir[MAXCACHE], *lastpat[MAXCACHE];
  131. static int lastn[MAXCACHE];
  132. static Dirlist *dirlist[MAXCACHE];
  133.  
  134. /********************************************************************
  135.  * Check if a particular directory is cached
  136.  ********************************************************************/
  137. static int
  138. is_cached(const char *dir, const char *pat, int *c)
  139. {
  140.     int cached = 0, i = 0;
  141.     static int lastcache;
  142.  
  143.     do
  144.       {
  145.       cached = lastpat[i] && lastdir[i] &&
  146.           strcmp(lastdir[i], dir) == 0 && strcmp(lastpat[i], pat) == 0 &&
  147.           (dirlist[i] && dirlist[i]->name);
  148.  
  149.       *c = i++;
  150.       }
  151.     while (!cached && i < MAXCACHE);
  152.  
  153.     /* search for the least used slot if not cached */
  154.     if (!cached)
  155.     *c = (++lastcache) % MAXCACHE;
  156.  
  157.     lastcache = *c;
  158.     M_info("CheckDirCache", "%s is %s cached", dir, cached ? "" : "not");
  159.     return cached;
  160. }
  161.  
  162. static void
  163. free_dirlist(Dirlist * dl)
  164. {
  165.  
  166.     while (dl && dl->name)
  167.       {
  168.       free(dl->name);
  169.       dl->name = 0;        /* important: signifies empty list */
  170.       dl++;
  171.       }
  172. }
  173.  
  174. void
  175. free_all_dirlist(void)
  176. {
  177.     int i;
  178.  
  179.     for (i = 0; i < MAXCACHE; i++)
  180.       {
  181.       free_dirlist(dirlist[i]);
  182.       dirlist[i] = 0;
  183.       }
  184. }
  185.  
  186.  
  187. /**********************************************************************
  188.  * The user callable routine to read a directory
  189.  *********************************************************************/
  190.  
  191. Dirlist *
  192. get_dir_list(const char *dir, const char *pattern, int *n, int rescan)
  193. {
  194.     int i, c;
  195.     const char *pat = pattern;
  196.     static char okdir[PATH_MAX + 1];
  197.  
  198.     if (!dir || !*dir)
  199.     return 0;
  200.  
  201.     if (!pat || !*pat)
  202.     pat = "*";
  203.  
  204.     /* fix the directory on the fly */
  205.     i = strlen(strcpy(okdir, dir));
  206.     if (okdir[i - 1] != '/')
  207.       {
  208.       okdir[i] = '/';
  209.       okdir[++i] = '\0';
  210.       }
  211.  
  212.  
  213.     /* is_cached must go first to get correct cache location */
  214.     if (!is_cached(okdir, pat, &c) || rescan)
  215.       {
  216.       free_dirlist(dirlist[c]);
  217.       dirlist[c] = 0;
  218.       lastn[c] = SysV_get_entries(okdir, pat, &dirlist[c]);
  219.       StrReDup(lastpat[c], pat);
  220.       StrReDup(lastdir[c], okdir);
  221.       }
  222.  
  223.     *n = lastn[c];
  224.     return dirlist[c];
  225. }
  226.  
  227.  
  228.  
  229. /***********************************************************************
  230.  * Misc. routines related directory
  231.  **********************************************************************/
  232. int
  233. is_valid_dir(const char *name)
  234. {
  235.     struct stat statbuf;
  236.  
  237.     return (stat(name, &statbuf) == 0 &&
  238.         (statbuf.st_mode & S_IFDIR) == S_IFDIR);
  239. }
  240.  
  241. /************************************************************************
  242.  * Remove all files, except directories from dir
  243.  ***********************************************************************/
  244. void
  245. rm_all_files(const char *dir, const char *pat)
  246. {
  247.     Dirlist *dl, *dls;
  248.     int n;
  249.  
  250.     push_dir();
  251.     chdir(dir);
  252.  
  253.     /* always re-read the directory entries */
  254.     dl = get_dir_list(dir, pat, &n, 1);
  255.  
  256.     if (dl && n > 0)
  257.       {
  258.       for (dls = dl + n; --dls >= dl;)
  259.         {
  260.         if (dls->type == FT_FILE)
  261.             if (remove(dls->name))
  262.             perror(dls->name);
  263.         }
  264.       }
  265.     pop_dir();
  266.     free_dirlist(dl);
  267. }
  268.  
  269. /************************************************************
  270.  * File modification time
  271.  ***********************************************************/
  272. unsigned long
  273. f_mtime(const char *s)
  274. {
  275.     struct stat fffstat;
  276.     stat(s, &fffstat);
  277.     return fffstat.st_mtime;
  278. }
  279.